package com.omuao.common.utils.http.impl;


import com.omuao.common.utils.http.ContentResult;
import com.omuao.common.utils.http.DataResult;
import com.omuao.common.utils.http.Result;
import com.omuao.common.utils.http.RowsResult;

import java.util.List;

/**
 * 返回结果
 *
 * @author yumi@omuao.com
 * @since 2019-10-11
 **/
public class ResultImpl<T> implements Result<T>, ContentResult<T>, DataResult<T> {

    /**
     * 成功
     */
    public static final int SUCCESS = 0;

    /**
     * 失败
     */
    public static final int FAILED = -1;

    /**
     * 超时
     */
    public static final int TIMEOUT = -2;

    /**
     * 未认证
     */
    public static final int NO_AUTH = -3;

    /**
     * 失效的访问
     */
    public static final int DEPRECATED = -4;

    /**
     * 未找到
     */
    public static final int NOT_FOUND = -5;

    /**
     * 解析格式异常
     */
    public static final int ANALYSIS_FORMAT = -6;

    /**
     * 请求成功
     */
    public static final int HTTP_SUCCESS = 200;


    /**
     * 状态码
     */
    private int status = HTTP_SUCCESS;

    /**
     * 错误码
     */
    private int code;

    /**
     * 状态信息
     */
    private String message;

    /**
     * 数据
     */
    private T data;

    /**
     * 主体数据
     */
    private List<T> bodyData;

    /**
     * 头部数据
     */
    private List<T> headerData;

    /**
     * 底部数据
     */
    private List<T> footerData;

    /**
     * 主体数据总数
     */
    private long total;

    /**
     * 主体数据分页总数
     */
    private long totalPages;

    @Override
    public int getStatus() {
        return status;
    }

    @Override
    public void setStatus(int status) {
        this.status = status;
    }

    @Override
    public int getCode() {
        return code;
    }

    @Override
    public void setCode(int code) {
        this.code = code;
    }

    @Override
    public String getMessage() {
        return message;
    }

    @Override
    public void setMessage(String message) {
        this.message = message;
    }

    @Override
    public T getData() {
        return data;
    }

    @Override
    public void setData(T data) {
        this.data = data;
    }

    @Override
    public List<T> getBodyData() {
        return bodyData;
    }

    @Override
    public void setBodyData(List<T> bodyData) {
        this.bodyData = bodyData;
    }

    @Override
    public List<T> getHeaderData() {
        return headerData;
    }

    @Override
    public void setHeaderData(List<T> headerData) {
        this.headerData = headerData;
    }

    @Override
    public List<T> getFooterData() {
        return footerData;
    }

    @Override
    public void setFooterData(List<T> footerData) {
        this.footerData = footerData;
    }

    @Override
    public long getTotal() {
        return total;
    }

    @Override
    public void setTotal(long total) {
        this.total = total;
    }

    @Override
    public long getTotalPages() {
        return totalPages;
    }

    @Override
    public void setTotalPages(long totalPages) {
        this.totalPages = totalPages;
    }

    @Override
    public String toString() {
        return "ResultImpl{" +
                "status=" + status +
                ", code=" + code +
                ", message='" + message + '\'' +
                ", data=" + data +
                ", bodyData=" + bodyData +
                ", headerData=" + headerData +
                ", footerData=" + footerData +
                ", total=" + total +
                ", totalPages=" + totalPages +
                '}';
    }

    public ResultImpl(int code, String message, T data, List<T> bodyData, List<T> headerData, List<T> footerData, long total, long totalPages) {
        this.code = code;
        this.message = message;
        this.data = data;
        this.bodyData = bodyData;
        this.headerData = headerData;
        this.footerData = footerData;
        this.total = total;
        this.totalPages = totalPages;
    }

    public ResultImpl() {
    }

    public static <T> Result<T> result(int code, String message, T data, List<T> bodyData, List<T> headerData, List<T> footerData, long total, long totalPages) {
        Result<T> result = null;
        if (code > -1) {

            if (bodyData != null && data != null) {
                return new ResultImpl(code, message, data, bodyData, headerData, footerData, total, totalPages);
            }

            if (footerData != null) {
                return new RowsResultExtImpl<>(code, message, bodyData, headerData, footerData, total, totalPages);
            }

            if (headerData != null) {
                return new RowsResultExtImpl<>(code, message, bodyData, headerData, null, total, totalPages);
            }

            if (bodyData != null) {
                return new RowsResultImpl<>(code, message, bodyData, total, totalPages);
            }

            if (data != null) {
                return new SingleResultImpl<>(code, message, data);
            }

            return new MessageResultImpl<>(code, message);


        } else {
            result = new ErrorResultImpl<>(HTTP_SUCCESS, code, message);
        }
        return result;
    }

    public static <T> Result success(String message, T data, List<T> bodyData, List<T> headerData, List<T> footerData, long total, long totalPages) {
        return result(SUCCESS, message, data, bodyData, headerData, footerData, total, totalPages);
    }

    public static <T> Result success(String message, T data) {
        return result(SUCCESS, message, data, null, null, null, 0, 0);
    }

    public static <T> Result success(String message, List<T> bodyData) {
        return result(SUCCESS, message, null, bodyData, null, null, 0, 0);
    }

    public static <T> Result success(String message, List<T> bodyData, List<T> headerData, List<T> footerData) {
        return result(SUCCESS, message, null, bodyData, headerData, footerData, 0, 0);
    }

    public static <T> Result success(String message, List<T> bodyData, long total, long totalPages) {
        return result(SUCCESS, message, null, bodyData, null, null, total, totalPages);
    }

    public static <T> Result success(String message, List<T> bodyData, List<T> headerData, List<T> footerData, long total, long totalPages) {
        return result(SUCCESS, message, null, bodyData, headerData, footerData, total, totalPages);
    }

    public static <T> Result success(String message, T data, List<T> bodyData, long total, long totalPages) {
        return result(SUCCESS, message, data, bodyData, null, null, total, totalPages);
    }

    public static Result<Object> resultObject(int code, String message, Object data, List<? extends Object> bodyData, List<? extends Object> headerData, List<? extends Object> footerData, long total, long totalPages) {
        ResultImpl result = new ResultImpl(code, message, data, bodyData, headerData, footerData, total, totalPages);
        return result;
    }

    public static Result successObject(String message, Object data, List<? extends Object> bodyData, List<? extends Object> headerData, List<? extends Object> footerData, long total, long totalPages) {
        return resultObject(SUCCESS, message, data, bodyData, headerData, footerData, total, totalPages);
    }

    public static Result successObject(String message, Object data) {
        return resultObject(SUCCESS, message, data, null, null, null, 0, 0);
    }

    public static Result successObject(String message, List<? extends Object> bodyData) {
        return resultObject(SUCCESS, message, null, bodyData, null, null, 0, 0);
    }

    public static Result successObject(String message, List<? extends Object> bodyData, List<? extends Object> headerData, List<? extends Object> footerData) {
        return resultObject(SUCCESS, message, null, bodyData, headerData, footerData, 0, 0);
    }

    public static Result successObject(String message, List<? extends Object> bodyData, long total, long totalPages) {
        return resultObject(SUCCESS, message, null, bodyData, null, null, total, totalPages);
    }

    public static Result successObject(String message, List<? extends Object> bodyData, List<? extends Object> headerData, List<? extends Object> footerData, long total, long totalPages) {
        return resultObject(SUCCESS, message, null, bodyData, headerData, footerData, total, totalPages);
    }

    public static Result successObject(String message, Object data, List<? extends Object> bodyData, long total, long totalPages) {
        return resultObject(SUCCESS, message, data, bodyData, null, null, total, totalPages);
    }

    public static <T> Result failed(String message) {
        return result(FAILED, message, null, null, null, null, 0, 0);
    }

    public static <T> Result timeout(String message) {
        return result(TIMEOUT, message, null, null, null, null, 0, 0);
    }

    public static <T> Result notFound(String message) {
        return result(NOT_FOUND, message, null, null, null, null, 0, 0);
    }

    public static <T> Result notAuth(String message) {
        return result(NO_AUTH, message, null, null, null, null, 0, 0);
    }

    public static <T> Result deprecated(String message) {
        return result(DEPRECATED, message, null, null, null, null, 0, 0);
    }

    public static <T> Result analysisFormatError(String message) {
        return result(ANALYSIS_FORMAT, message, null, null, null, null, 0, 0);
    }

    private static class RowsResultExtImpl<T> implements ContentResult<T> {
        /**
         * 状态码
         */
        private int status = HTTP_SUCCESS;

        /**
         * 错误码
         */
        private int code;

        /**
         * 状态信息
         */
        private String message;


        /**
         * 主体数据
         */
        private List<T> bodyData;

        /**
         * 头部数据
         */
        private List<T> headerData;

        /**
         * 底部数据
         */
        private List<T> footerData;

        /**
         * 主体数据总数
         */
        private long total;

        /**
         * 主体数据分页总数
         */
        private long totalPages;

        public RowsResultExtImpl() {
        }

        public RowsResultExtImpl(int code, String message, List<T> bodyData, List<T> headerData, List<T> footerData, long total, long totalPages) {
            this.code = code;
            this.message = message;
            this.bodyData = bodyData;
            this.headerData = headerData;
            this.footerData = footerData;
            this.total = total;
            this.totalPages = totalPages;
        }

        @Override
        public int getStatus() {
            return status;
        }

        @Override
        public void setStatus(int status) {
            this.status = status;
        }

        @Override
        public int getCode() {
            return code;
        }

        @Override
        public void setCode(int code) {
            this.code = code;
        }

        @Override
        public String getMessage() {
            return message;
        }

        @Override
        public void setMessage(String message) {
            this.message = message;
        }

        @Override
        public List<T> getBodyData() {
            return bodyData;
        }

        @Override
        public void setBodyData(List<T> bodyData) {
            this.bodyData = bodyData;
        }

        @Override
        public List<T> getHeaderData() {
            return headerData;
        }

        @Override
        public void setHeaderData(List<T> headerData) {
            this.headerData = headerData;
        }

        @Override
        public List<T> getFooterData() {
            return footerData;
        }

        @Override
        public void setFooterData(List<T> footerData) {
            this.footerData = footerData;
        }

        @Override
        public long getTotal() {
            return total;
        }

        @Override
        public void setTotal(long total) {
            this.total = total;
        }

        @Override
        public long getTotalPages() {
            return totalPages;
        }

        @Override
        public void setTotalPages(long totalPages) {
            this.totalPages = totalPages;
        }

        @Override
        public String toString() {
            return "RowsResultExtImpl{" +
                    "status=" + status +
                    ", code=" + code +
                    ", message='" + message + '\'' +
                    ", bodyData=" + bodyData +
                    ", headerData=" + headerData +
                    ", footerData=" + footerData +
                    ", total=" + total +
                    ", totalPages=" + totalPages +
                    '}';
        }
    }

    private static class RowsResultImpl<T> implements RowsResult<T> {
        /**
         * 状态码
         */
        private int status = HTTP_SUCCESS;

        /**
         * 错误码
         */
        private int code;

        /**
         * 状态信息
         */
        private String message;

        /**
         * 主体数据
         */
        private List<T> bodyData;

        /**
         * 主体数据总数
         */
        private long total;

        /**
         * 主体数据分页总数
         */
        private long totalPages;

        public RowsResultImpl() {
        }

        public RowsResultImpl(int code, String message, List<T> bodyData, long total, long totalPages) {
            this.code = code;
            this.message = message;
            this.bodyData = bodyData;
            this.total = total;
            this.totalPages = totalPages;
        }

        @Override
        public int getStatus() {
            return status;
        }

        @Override
        public void setStatus(int status) {
            this.status = status;
        }

        @Override
        public int getCode() {
            return code;
        }

        @Override
        public void setCode(int code) {
            this.code = code;
        }

        @Override
        public String getMessage() {
            return message;
        }

        @Override
        public void setMessage(String message) {
            this.message = message;
        }

        @Override
        public List<T> getBodyData() {
            return bodyData;
        }

        @Override
        public void setBodyData(List<T> bodyData) {
            this.bodyData = bodyData;
        }

        @Override
        public long getTotal() {
            return total;
        }

        @Override
        public void setTotal(long total) {
            this.total = total;
        }

        @Override
        public long getTotalPages() {
            return totalPages;
        }

        @Override
        public void setTotalPages(long totalPages) {
            this.totalPages = totalPages;
        }

        @Override
        public String toString() {
            return "RowsResultImpl{" +
                    "status=" + status +
                    ", code=" + code +
                    ", message='" + message + '\'' +
                    ", bodyData=" + bodyData +
                    ", total=" + total +
                    ", totalPages=" + totalPages +
                    '}';
        }
    }

    private static class SingleResultImpl<T> implements DataResult<T> {

        public SingleResultImpl() {
        }

        public SingleResultImpl(int code, String message, T data) {
            this.code = code;
            this.message = message;
            this.data = data;
        }

        /**
         * 状态码
         */
        private int status = HTTP_SUCCESS;

        /**
         * 错误码
         */
        private int code;

        /**
         * 状态信息
         */
        private String message;

        /**
         * 数据
         */
        private T data;

        @Override
        public int getStatus() {
            return status;
        }

        @Override
        public void setStatus(int status) {
            this.status = status;
        }

        @Override
        public int getCode() {
            return code;
        }

        @Override
        public void setCode(int code) {
            this.code = code;
        }

        @Override
        public String getMessage() {
            return message;
        }

        @Override
        public void setMessage(String message) {
            this.message = message;
        }

        @Override
        public T getData() {
            return data;
        }

        @Override
        public void setData(T data) {
            this.data = data;
        }

        @Override
        public String toString() {
            return "SingleResultImpl{" +
                    "status=" + status +
                    ", code=" + code +
                    ", message='" + message + '\'' +
                    ", data=" + data +
                    '}';
        }
    }

    private static class MessageResultImpl<T> implements Result<T> {

        public MessageResultImpl() {
        }

        public MessageResultImpl(int code, String message) {
            this.code = code;
            this.message = message;
        }

        /**
         * 状态码
         */
        private int status = HTTP_SUCCESS;

        /**
         * 错误码
         */
        private int code;

        /**
         * 状态信息
         */
        private String message;

        @Override
        public int getStatus() {
            return status;
        }

        @Override
        public void setStatus(int status) {
            this.status = status;
        }

        @Override
        public int getCode() {
            return code;
        }

        @Override
        public void setCode(int code) {
            this.code = code;
        }

        @Override
        public String getMessage() {
            return message;
        }

        @Override
        public void setMessage(String message) {
            this.message = message;
        }

        @Override
        public String toString() {
            return "MessageResultImpl{" +
                    "status=" + status +
                    ", code=" + code +
                    ", message='" + message + '\'' +
                    '}';
        }
    }


    private static class ErrorResultImpl<T> implements Result<T> {
        public ErrorResultImpl() {
        }

        public ErrorResultImpl(int status, int code, String message) {
            this.status = status;
            this.code = code;
            this.message = message;
        }

        /**
         * 状态码
         */
        private int status = HTTP_SUCCESS;

        /**
         * 错误码
         */
        private int code;

        /**
         * 状态信息
         */
        private String message;

        @Override
        public int getStatus() {
            return status;
        }

        @Override
        public void setStatus(int status) {
            this.status = status;
        }

        @Override
        public int getCode() {
            return code;
        }

        @Override
        public void setCode(int code) {
            this.code = code;
        }

        @Override
        public String getMessage() {
            return message;
        }

        @Override
        public void setMessage(String message) {
            this.message = message;
        }

        @Override
        public String toString() {
            return "ErrorResultImpl{" +
                    "status=" + status +
                    ", code=" + code +
                    ", message='" + message + '\'' +
                    '}';
        }
    }
}
